﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Configuration;
using System.Collections;
using System.Threading;
using commonlib;

namespace puppetmaster
{
    public partial class Form1 : Form
    {

        Process centralDirectoryProcess;
        PuppetMasterServices puppetMasterServices;

        Hashtable clientProcessesList = new Hashtable();
        Hashtable dataServersProcessesList = new Hashtable();
        Hashtable itemsContainers = new Hashtable();

        List<string> commands;

        public Form1()
        {
            InitializeComponent();
            puppetMasterServices = new PuppetMasterServices();
            commands = new List<string>();
            activateCommandsMenuItems(false);
        }

        /**
         * Abrir a janela de escolha do ficheiro
         **/
        private void abrirToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string file = OpenScript();

            if (file != null)
            {
                StreamReader tr = new StreamReader(file);
                string line = "";

                while (!tr.EndOfStream)
                {
                    line = tr.ReadLine();
                    commands.Add(line);
                }

                if (commands.Count > 0)
                    activateCommandsMenuItems(true);

                //  this.lstBxRegisteredClients.Items.AddRange(commands.ToArray());
            }
        }

        /**
         * Inicializar as opções de menu e items da interface do puppetmaster
         **/
        private void activateCommandsMenuItems(bool state)
        {
            this.runLoadedScriptToolStripMenuItem.Enabled = state;
            this.runStepNToolStripMenuItem.Enabled = state;
            this.txtCentralDirectoryStatus.Text = "Off";
        }

        /**
         * Abrir o script de comandos
         **/
        private string OpenScript()
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            dialog.Title = "Select a script";
            return (dialog.ShowDialog() == DialogResult.OK)
               ? dialog.FileName : null;
        }

        /**
    * Inicia a Execucao dos comandos lidos do ficheiro 
    **/
        private void runLoadedScript()
        {
            string[] elements;
            foreach (string line in commands)
            {
                elements = line.Split(' ');
                //Thread.Sleep(500);-- temporizacao entre as conexoes dos componentes do sistema
                if (elements[0].Contains("connect"))
                {

                    if (elements[1].Contains("central"))
                    {
                        string[] token = elements[2].Split(':');
                        string address = token[0];
                        int port = Convert.ToInt16(token[1]);
                        startCentralDirectory("central", address, port);

                    }

                    if (elements[1].Contains("server"))
                    {
                        string[] token = elements[2].Split(':');
                        string address = token[0];
                        int port = Convert.ToInt16(token[1]);
                        int count = this.dataServersProcessesList.Count;
                        count++;
                        startDataServer("server" + count, address, port);
                    }

                    if (elements[1].Contains("client"))
                    {
                        string[] token = elements[2].Split(':');
                        string address = token[0];
                        int port = Convert.ToInt16(token[1]);
                        int count = this.clientProcessesList.Count;
                        count++;
                        startClient("client" + count, address, port);
                    }
                }
            }

            //this.puppetMasterServices.updateDataServers();
        }

        /**
         * Inicia a execucao do Central Directory
         **/
        private void startCentralDirectory(string name, string address, int port)
        {
            centralDirectoryProcess = new Process();
            centralDirectoryProcess.StartInfo.FileName = ConfigurationManager.AppSettings["central_directory_path"];
            centralDirectoryProcess.StartInfo.Arguments = name + " " + address + " " + port;
            centralDirectoryProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
            centralDirectoryProcess.Start();
            this.txtCentralDirectoryStatus.Text = "On";
            this.txtTotalItems.Text = "0";
            this.puppetMasterServices.centralAddress = address;
            this.puppetMasterServices.centralPort = port;
            /*
            if(this.puppetMasterServices.init())
                MessageBox.Show("initiated central directory services reference. " + this.puppetMasterServices.dataServers.Count);
            else
                MessageBox.Show("failed to initiate central directory services reference.");
             * */
        }

        /**
         * Inicia a execucao do client
         **/
        private void startClient(string name, string address, int port)
        {
            Process newClient = new Process();
            newClient.StartInfo.FileName = ConfigurationManager.AppSettings["client_path"];
            newClient.StartInfo.Arguments = name + " " + address + " " + port;
            newClient.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
            newClient.Start();

            clientProcessesList.Add(name, newClient);
            this.lstBxRegisteredClients.Items.Add(name);
        }

        /**
         * Inicia a execucao do data server
         **/
        private void startDataServer(string name, string address, int port)
        {
            Process newDataServer = new Process();
            newDataServer.StartInfo.FileName = ConfigurationManager.AppSettings["data_server_path"];
            newDataServer.StartInfo.Arguments = name + " " + address + " " + port;
            newDataServer.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
            newDataServer.Start();

            dataServersProcessesList.Add(name, newDataServer);
            this.lstBxRegisteredDataServers.Items.Add(name);
        }

        /**
        * Executa o término dos processos do sistema ao sair do sistema 
        **/
        private void sairToolStripMenuItem_Click(object sender, EventArgs e)
        {
            exitAllSystemProcesses();
            Application.Exit();
        }

        /**
         * Termina todos os processos em execucao
         **/
        private void exitAllSystemProcesses()
        {
            if (isProcessRunning("central"))
            {
                centralDirectoryProcess.Kill();
                this.txtCentralDirectoryStatus.Text = "Off";
            }

            IDictionaryEnumerator processes = clientProcessesList.GetEnumerator();
            Process p;

            while (processes.MoveNext())
            {
                p = (Process)processes.Value;
                p.Kill();
            }

            processes = dataServersProcessesList.GetEnumerator();
            while (processes.MoveNext())
            {
                p = (Process)processes.Value;
                p.Kill();

            }
        }

        /**
         * Verifica se um processo está em execução
         **/
        private Boolean isProcessRunning(string name)
        {
            foreach (Process clsProcess in Process.GetProcesses())
            {
                if (clsProcess.ProcessName.Contains(name))
                    return true;
            }

            return false;
        }
        
        /**
         * Executa o script carregado
         **/
        private void runLoadedScriptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            runLoadedScript();
        }

        /**
         * Disconectar o servidor de dados selecionado
         **/
        private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
            if (this.lstBxRegisteredDataServers.SelectedItem != null)
            {
                // Get the currently selected item in the ListBox.
                string dataServerName = this.lstBxRegisteredDataServers.SelectedItem.ToString();
                
                // Find the string in ListBox2.
                int index = this.lstBxRegisteredDataServers.FindString(dataServerName);
                // If the item was not found in ListBox 2 display a message box, otherwise select it in ListBox2.
                if (index == -1)
                    MessageBox.Show("Não foi selecionado um data server na lista");
                else
                    this.lstBxRegisteredDataServers.SetSelected(index, true);

                MessageBox.Show("" + this.puppetMasterServices.updateDataServers());

                MessageBox.Show(""+this.puppetMasterServices.dataServers.Count);
                /*
                if (puppetMasterServices.changeDataServerState(dataServerName, STATES.OFFLINE))
                    MessageBox.Show(dataServerName + " está ");

               */
            }else
                MessageBox.Show("Não foi selecionado um data server na lista");
           
        }

       /**
        * Conectar o servidor de dados selecionado
        **/
        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            /*
            if (this.lstBxRegisteredDataServers.SelectedItem != null)
            {
                // Get the currently selected item in the ListBox.
                string dataServerName = this.lstBxRegisteredDataServers.SelectedItem.ToString();

                // Find the string in ListBox2.
                int index = this.lstBxRegisteredDataServers.FindString(dataServerName);
                // If the item was not found in ListBox 2 display a message box, otherwise select it in ListBox2.
                if (index == -1)
                    MessageBox.Show("Não foi selecionado um data server na lista");
                else
                    this.lstBxRegisteredDataServers.SetSelected(index, true);

                if (puppetMasterServices.changeDataServerState(dataServerName, STATES.ONLINE))
                    MessageBox.Show(dataServerName + " está " + STATES.ONLINE.ToString("Online"));
                else
                    MessageBox.Show(dataServerName + " já estava " + STATES.ONLINE.ToString("Online"));

            }
            else
                MessageBox.Show("Não foi selecionado um data server na lista");
             * */
        }

    }
}
